<?php
namespace app\user\model;

use think\Model;
use Aliyun\SignatureHelper;

class Smscode extends Model {
    const UNKNOW = 0, LOGIN = 1, REGISTER = 2, RESET_PASSWORD = 3;
    const EXPIRE = 600;
    const COUNTDOWN = 120;
    protected $pk = ['mobile_num', 'scene'];
    private $config;

    public function initialize(): void {
        $this->config = config('app.SMS');
        parent::initialize();
    }

    public static function isValidMobileNum(int $mobileNum): bool {
        return preg_match('/^(1)\d{10}$/', strval($mobileNum)) != null;
    }

    public static function verify(int $mobileNum, int $scene, int $code): bool {
        self::cleanOutdated();
        //从数据库中读取
        $data = self::where(['mobile_num' => $mobileNum, 'scene' => $scene])->find();
        if($data){
            return $data['code'] == $code;
        } else {
            return false;
        }
    }

    public static function cleanOutdated(){
        self::where('expire', '<', time())->delete();
    }

    public static function getCountdownTime(int $mobileNum, int $scene = 0): ?int {
        self::cleanOutdated();
        $sender = self::where(['mobile_num' => $mobileNum, 'scene' => $scene])->find();
        $time = time();
        if($sender){
            $sendTime = $sender->send_time;
            if($time >= $sendTime + self::COUNTDOWN){
                return null;
            } else {
                return $sendTime + self::COUNTDOWN;
            }
            return $sender->send_time;
        } else {
            return null;
        }
    }

    public static function buildNewCode(int $mobileNum, int $scene = 0): self {
        $data = new self();
        $data->mobile_num = $mobileNum;
        $data->scene = $scene;
        $data->code = mt_rand(100000, 999999);
        $data->send_time = 0;
        $data->expire = 0;
        $data->save();
        return $data;
    }

    public static function getSender(int $mobileNum, int $scene = 0): self {
        self::cleanOutdated();
        $sender = self::where(['mobile_num' => $mobileNum, 'scene' => $scene])->find();
        if(!$sender){
            $sender = self::buildNewCode($mobileNum, $scene);
        }
        return $sender;
    }

    public static function getErrorMsg(string $code): string {
        $errorMsg = [
			'isp.RAM_PERMISSION_DENY' => 'RAM权限DENY',
			'isv.OUT_OF_SERVICE' => '业务停机',
			'isv.PRODUCT_UNSUBSCRIBE' => '产品未开通',
			'isv.ACCOUNT_NOT_EXISTS' => '账户不存在',
			'isv.ACCOUNT_ABNORMAL' => '账户异常',
			'isv.SMS_TEMPLATE_ILLEGAL' => '短信模板不合法',
			'isv.SMS_SIGNATURE_ILLEGAL' => '短信签名不合法',
			'isv.INVALID_PARAMETERS' => '参数异常',
			'isp.SYSTEM_ERROR' => '服务器内部错误',
			'isv.MOBILE_NUMBER_ILLEGAL' => '手机号不正确',
			'isv.MOBILE_COUNT_OVER_LIMIT' => '手机号码数量超过限制',
			'isv.TEMPLATE_MISSING_PARAMETERS' => '	模板缺少变量',
			'isv.BUSINESS_LIMIT_CONTROL' => '短信发送过于频繁，请稍后再试',
			'isv.INVALID_JSON_PARAM' => 'JSON参数不合法，只接受字符串值',
			'isv.BLACK_KEY_CONTROL_LIMIT' => '	黑名单管控',
			'isv.PARAM_LENGTH_LIMIT' => '参数超出长度限制',
			'isv.PARAM_NOT_SUPPORT_URL' => '不支持URL',
			'isv.AMOUNT_NOT_ENOUGH' => '账户余额不足',
			'isv.TEMPLATE_PARAMS_ILLEGAL' => '模板变量里包含非法关键字',
			'net.NOTCONNECT' => '无法访问接口',
			'default' => '暂无相关错误介绍',
			'ctx.UNDEFINED' => '接口返回数据不正确',
		];
		if(isset($errorMsg[$code])){
			return $errorMsg[$code];
		} else {
			return $code;
		}
    }

    /**
     * 以当前配置发送短信
     * @return string 发送的结果
     */
    public function sendSms(): string {
        $time = time();
        if($time < $this->getAttr('send_time') + self::COUNTDOWN){ //发送过于频繁
            return 'isv.BUSINESS_LIMIT_CONTROL';
        } else {
            /*$params = [
                'PhoneNumbers' => $this->getAttr('mobile_num'),
                'SignName' => $this->config['SignName'],
                'TemplateCode' => $this->config['TemplateCode'],
                'TemplateParam' => [
                    'code' => $this->getAttr('code'),
                ],
            ];
            try {
                if(!empty($params["TemplateParam"]) && is_array($params["TemplateParam"])) {
                    $params["TemplateParam"] = json_encode($params["TemplateParam"], JSON_UNESCAPED_UNICODE);
                    $helper = new SignatureHelper();
                    $content = $helper->request(
                        $this->config['accessKeyId'],
                        $this->config['accessKeySecret'],
                        "dysmsapi.aliyuncs.com",
                        array_merge($params, array(
                            "RegionId" => "cn-hangzhou",
                            "Action" => "SendSms",
                            "Version" => "2017-05-25",
                        ))
                        ,true
                    );
                    if(isset($content->Code)){
                        if($content->Code === 'OK'){
                            $time = time();
                            $this->setAttr('send_time', $time);
                            $this->setAttr('expire', $time + self::EXPIRE);
                            $this->save();
                        }
                        return $content->Code;
                    } else {
                        return 'ctx.UNDEFINED';
                    }
                }
                
            } catch(Exception $e){
                return 'net.NOTCONNECT';
            }*/
            /* 测试专用 */
            $time = time();
            $this->setAttr('send_time', $time);
            $this->setAttr('expire', $time + self::EXPIRE);
            $this->save();
            return 'OK';
        }
	}
}